package com.michaelbulava.TFS.vcs.internal.environments;

import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.update.SequentialUpdatesContext;
import com.intellij.openapi.vcs.update.UpdateEnvironment;
import com.intellij.openapi.vcs.update.UpdateSession;
import com.intellij.openapi.vcs.update.UpdatedFiles;
import com.michaelbulava.TFS.Messages;
import com.michaelbulava.TFS.vcs.TFSVcs;
import com.michaelbulava.TFS.vcs.exceptions.TFSException;
import com.michaelbulava.TFS.vcs.internal.conflicts.ConflictsEnvironment;
import com.michaelbulava.TFS.vcs.internal.conflicts.ResolveConflictHelper;
import com.michaelbulava.TFS.vcs.internal.WorkstationHelper;
import com.michaelbulava.TFS.vcs.utils.TFSFileUtil;
import com.michaelbulava.TFS.vcs.utils.TFSProgressUtil;
import com.michaelbulava.TFS.vcs.utils.TFSUtil;
import com.microsoft.tfs.core.clients.versioncontrol.GetOptions;
import com.microsoft.tfs.core.clients.versioncontrol.GetStatus;
import com.microsoft.tfs.core.clients.versioncontrol.soapextensions.Conflict;
import com.microsoft.tfs.core.clients.versioncontrol.soapextensions.GetRequest;
import com.microsoft.tfs.core.clients.versioncontrol.soapextensions.Workspace;
import com.microsoft.tfs.core.clients.versioncontrol.specs.version.LatestVersionSpec;
import com.microsoft.tfs.core.clients.versioncontrol.specs.version.VersionSpec;
import com.microsoft.tfs.util.Check;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.*;
import java.util.concurrent.atomic.AtomicReference;

/**
 * Created by MichaelA on 8/10/2015.
 */
public class TFSUpdateEnvironment implements UpdateEnvironment {
    private final TFSVcs myVcs;

    public TFSUpdateEnvironment(TFSVcs vcs) {
        Check.notNull(vcs, "vcs");
        this.myVcs = vcs;
    }


    @Override
    public void fillGroups(UpdatedFiles updatedFiles) {}

    @NotNull
    @Override
    public UpdateSession updateDirectories(FilePath[] filePaths, UpdatedFiles updatedFiles,
                                           ProgressIndicator progressIndicator, Ref<SequentialUpdatesContext> context)
            throws ProcessCanceledException {
        UpdateSession updateSession;
        final List<VcsException> exceptions = new ArrayList<>();
        Check.notNull(filePaths, "filePaths");
        Check.notNull(context, "context");

        //TODO Update Progress
        TFSProgressUtil.setProgressText(progressIndicator, Messages.getString("TFSUpdateEnvironment.RequestUpdate"));
        try{
            final Map<Workspace, Conflict[]> workspace2Conflicts = new HashMap<>();
            List<FilePath> orphanPaths = WorkstationHelper.processByWorkspaces(Arrays.asList(filePaths), true,
                    myVcs.getProject(), new WorkstationHelper.VoidDelegateProcess() {
                        @Override
                        public void executeRequest(Workspace workspace, List<FilePath> localPaths) throws TFSException {
                            VersionSpec version = LatestVersionSpec.INSTANCE;
                            //RecursionType recursionType = RecursionType.FULL;
                            boolean recursive = true;
                            //TODO We should be displaying a window when an update is requested, if we do we need to pull
                            //the versionSpec and RecursionType from what was selected.

                            //ItemSpec[] items = TFSFileUtil.getItemSpecs(myVcs.getProject(), workspace, localPaths, recursive);
                            GetRequest[] requests = TFSFileUtil.getGetRequests(myVcs.getProject(), workspace, localPaths,
                                    version, recursive);
                            AtomicReference<Conflict[]> conflicts = new AtomicReference<Conflict[]>();


                            GetStatus status = workspace.get(requests, GetOptions.GET_ALL, (String[])null, true, conflicts);


                            exceptions.addAll(TFSUtil.getVcsExceptions(status.getFailures()));
                            if (conflicts.get()!= null && conflicts.get().length > 0)
                                workspace2Conflicts.put(workspace, conflicts.get());
                        }
                    });
            if (!workspace2Conflicts.isEmpty()){
                ResolveConflictHelper resolveConflictHelper = new ResolveConflictHelper(myVcs.getProject(),
                        workspace2Conflicts, updatedFiles);
                ConflictsEnvironment.getConflictsHandler().resolveConflicts(resolveConflictHelper);
            }

        } catch (TFSException e) {
            exceptions.add(new VcsException(e));
        }
        TFSFileUtil.refreshAndInvalidate(myVcs.getProject(), filePaths, false);
        updateSession = new UpdateSession() {
            @NotNull
            @Override
            public List<VcsException> getExceptions() {
                return exceptions;
            }

            @Override
            public void onRefreshFilesCompleted() {
                myVcs.fireRevisionChanged();
            }

            @Override
            public boolean isCanceled() {
                return false;
            }
        };
        return updateSession;
    }

    @Nullable
    @Override
    public Configurable createConfigurable(Collection<FilePath> collection) {
        return null;
    }

    @Override
    public boolean validateOptions(Collection<FilePath> collection) {
        return true;
    }



}
